package com.ruoyi.system.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.ruoyi.common.config.BigDataConfig;
import com.ruoyi.common.config.FtpConfig;
import com.ruoyi.common.core.domain.JSONObjectPro;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.page.Page;
import com.ruoyi.common.enums.comlbs.ActivateStatusEnum;
import com.ruoyi.common.enums.comlbs.VehicleStatusEnum;
import com.ruoyi.common.exception.BigDataException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.http.BigDataResponse;
import com.ruoyi.common.utils.http.HttpRequest;
import com.ruoyi.system.domain.AlarmType;
import com.ruoyi.system.domain.request.bigscreen.AlarmStatisticsParam;
import com.ruoyi.system.domain.request.bigscreen.AvgOnlineRateParam;
import com.ruoyi.system.domain.request.bigscreen.PhotoStatisticsParam;
import com.ruoyi.system.domain.vo.bigscreen.DeviceDriver;
import com.ruoyi.system.domain.vo.common.DeviceGps;
import com.ruoyi.system.domain.vo.equipment.EquipmentInfo;
import com.ruoyi.system.domain.vo.reportstatistics.Photo;
import com.ruoyi.system.service.*;
import com.ruoyi.system.utils.ComLbsUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 描述
 * 作者 ZhangPing
 * 创建时间 2023/9/26 16:20
 */
@Slf4j
@Service
public class BigScreenServiceImpl implements BigScreenService {

    @Autowired
    private IEquipmentManagementService equipmentManagementService;
    @Autowired
    private CommonService commonService;
    @Autowired
    private ISysDeptService deptService;
    @Autowired
    private BigDataConfig bigDataConfig;
    @Autowired
    private FtpConfig ftpConfig;
    @Autowired
    private IAlarmTypeService alarmTypeService;

    /**
     * 设备统计
     * @return
     */
    @Override
    public JSONObject deviceStatistics(AvgOnlineRateParam param){
        //查询所有设备
        List<EquipmentInfo> equipmentList = equipmentManagementService.selectList(new EquipmentInfo()
                .setActivateStatus(ActivateStatusEnum.ACTIVATED.getCode()) //已激活设备
                .setNumberPlateNotEmpty(true));//设备名称不为空
        List<String> deviceIdList = equipmentList.stream().map(EquipmentInfo::getDeviceId).collect(Collectors.toList());
        //获取设备状态数据
        Map<String, DeviceGps> deviceGpsMap = commonService.getDeviceOnlineDataFromService(null);
        //计算车辆状态
        long drivingCount = 0;
        long stopCount = 0;
        long flameOutCount = 0;
        long positioningFailCount = 0;
        long offlineCount = 0;
        for (String deviceId : deviceIdList) {
            DeviceGps deviceGps = deviceGpsMap.get(deviceId);
            if (deviceGps == null) continue;
            VehicleStatusEnum vehicleStatus = ComLbsUtils.getVehicleStatus(deviceGps);
            if (vehicleStatus == VehicleStatusEnum.NOT_LOCATE) continue;
            switch (vehicleStatus){
                case DRIVING:
                    drivingCount++;
                    break;
                case STOP:
                    stopCount++;
                    break;
                case FLAME_OUT:
                    flameOutCount++;
                    break;
                case POSITIONING_FAIL:
                    positioningFailCount++;
                    break;
                case OFFLINE:
                    offlineCount++;
                    break;
            }
        }

        List<Long> deptIds = deptService.selectPermissionDeptId(param.getCompanyId());
        // 将List<Long>转换为逗号分隔的字符串（示例：1,2,3）
        String companyIdsStr = deptIds.stream()
                .map(String::valueOf)
                .collect(Collectors.joining(","));

        //设备统计数据
        BigDataResponse<JSONObject> response1 = HttpRequest.getBigDataNoEncode(bigDataConfig.getApiUrl() + "/dws/device/status/sta", new JSONObjectPro(), JSONObject.class);
        if (!response1.isSuccess()) throw new BigDataException();

        BigDataResponse.PageData<JSONObject> pageData = response1.getData();
        List<JSONObject> dataItems = pageData.getDataItems();

        int netCar = 0;
        int onlineCar = 0;
        if (dataItems.size() > 0 ) {
            JSONObject deviceCountJson = dataItems.get(0);
            netCar = deviceCountJson.getIntValue("totalNum");
            onlineCar = deviceCountJson.getIntValue("onlineNum");
        }

        JSONObjectPro bitDataParam = new JSONObjectPro()
                .put("companyIds", companyIdsStr)
                .put("startTime", DateUtils.parseToTimestamp(param.getStartTime()))
                .put("endTime", DateUtils.parseToTimestamp(DateUtils.addDay(param.getEndTime(), 1)));
        BigDataResponse<JSONObject> response2 = HttpRequest.getBigDataNoEncode(bigDataConfig.getApiUrl() + "/ads/company/rate/list", bitDataParam,JSONObject.class);
        if (!response2.isSuccess()) throw new BigDataException();
        // 上线数
        double sumOnline = response2.getData().getDataItems().stream().mapToDouble(i -> i.getIntValue("onlineNum")).sum();
        // 统计范围内车辆总数
        double sumTotal = response2.getData().getDataItems().stream().mapToDouble(i -> i.getIntValue("allNum")).sum();
        // 平均上线率
        double agvOnlineRate = sumTotal == 0 ? 0D : ComLbsUtils.round45(sumOnline * 100D / sumTotal);
        JSONObjectPro resJson = new JSONObjectPro()
                .put("totalCount", netCar)
                .put("onlineCount", onlineCar)
                .put("nowOnlineRate", netCar == 0 ? 0.0D : ComLbsUtils.round45(onlineCar * 100D / netCar))
                .put("agvOnlineRate", agvOnlineRate)
                .put("deviceStatus", new JSONObjectPro()
                .put("drivingCount", drivingCount)
                .put("stopCount", stopCount)
                .put("flameOutCount", flameOutCount)
                .put("positioningFailCount", positioningFailCount)
                .put("offlineCount", offlineCount));
        return resJson;
    }

    /**
     * 设备里程排行
     * @return
     */
    @Override
    public JSONObject deviceMileageRank(AvgOnlineRateParam param){

        JSONObjectPro bitDataParam = new JSONObjectPro()
                .put("page", 1)
                .put("size", 50)
                .put("desc", "total_mile");

        //获取有权限的公司ID
        List<Long> deptIdList = new ArrayList<>();
        if (param.getCompanyId() != null && param.getCompanyId() > 0) {
            deptIdList = deptService.selectPermissionDeptId(param.getCompanyId());
            // 将List<Long>转换为逗号分隔的字符串（示例：1,2,3）
            String companyIdsStr = deptIdList.stream()
                    .map(String::valueOf)
                    .collect(Collectors.joining(","));
            bitDataParam.put("companyIds", companyIdsStr);
        }

        BigDataResponse<JSONObject> response = HttpRequest.getBigDataNoEncode(bigDataConfig.getApiUrl() + "/dws/device/status/page", bitDataParam, JSONObject.class);
        if (!response.isSuccess()) throw new BigDataException();

        List<JSONObject> list = response.getData().getDataItems();
        // 按设备号分组
        Map<String, List<JSONObject>> deviceIdMap = list.stream().collect(Collectors.groupingBy(i -> i.getString("dvo")));

        Map<Long, String> deptMap = deptService.selectDeptList(new SysDept()).stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getShortName));

        List<JSONObject> resultList = new ArrayList<>();
        // 查询负责人信息
        List<DeviceDriver> driverList = equipmentManagementService.listDriver(deptIdList);
        Map<String, String> driverMap = ObjectUtils.isEmpty(driverList) ? Collections.emptyMap() : driverList.stream()
                .filter(i -> StringUtils.isNotEmpty(i.getDriverName()))
                .collect(Collectors.toMap(DeviceDriver::getDeviceId, DeviceDriver::getDriverName));
        // 总里程之和
        double totalMileage = 0;
        for (String deviceId : deviceIdMap.keySet()) {
            List<JSONObject> items = deviceIdMap.get(deviceId);
            JSONObject item = items.get(0);
            Long companyId = item.getLongValue("companyId");
            double kilometer = items.stream().mapToDouble(i -> i.getDoubleValue("totalMile")).sum();
            kilometer = ComLbsUtils.round45(kilometer);
            totalMileage += kilometer;
            resultList.add(new JSONObjectPro()
                    .put("deviceId", item.getString("dvo"))
                    .put("companyName", deptMap.getOrDefault(companyId, ""))
                    .put("numberPlate", item.getString("numberPlate"))
                    .put("kilometre", kilometer/1000.0));
        }
        // 按里程倒序排行，并取前50个
//        resultList.sort(Comparator.comparing((JSONObject i) -> i.getDoubleValue("totalMile")).reversed());
        resultList = resultList.subList(0, Math.min(50, resultList.size()));
        resultList.stream().forEach(i -> i.put("driverName", driverMap.get(i.getString("deviceId"))));
        return new JSONObjectPro()
                .put("totalMileage", totalMileage/1000.0)
                .put("list", resultList);
    }

    /**
     * 拍照统计
     * @return
     */
    @Override
    public JSONObject photoStatistics(PhotoStatisticsParam param){
        List<Long> deptIds = deptService.selectPermissionDeptId(param.getCompanyId());
        JSONObject bitDataParam = new JSONObjectPro()
                .put("pageSize", param.getPageSize())
                .put("pageIndex", param.getPageNum())
                .put("companyId", deptIds)
                .put("startTime", param.getStartTime())
                .put("endTime", param.getEndTime());
//        BigDataResponse<JSONObject> response = HttpRequest.postJsonBigData(bigDataConfig.getApiUrl() + "/photo/queryPage", bitDataParam, JSONObject.class);
//        if (!response.isSuccess()) throw new BigDataException();
        List<Photo> resultList = new ArrayList<>();
        int total = 0;
//        int total = response.getData().getIntValue("totalCount");
//        List<JSONObject> dataItems = response.getData().getList("dataItems", JSONObject.class);
//        List<Photo> resultList = dataItems.stream().map(item -> {
//            Photo photo = new Photo()
//                    .setCompanyName(item.get("companyName").toString())
//                    .setDvo(item.get("dvo").toString())
//                    .setNumberPlate(item.get("numberPlate").toString())
//                    .setChannelId((int) item.get("channelId"));
//            if (item.get("MediaPath") != null){
//                photo.setPictureUrl(ftpConfig.ftp2Http(item.get("MediaPath").toString()));
//            }
//            JSONObject gpsData = item.getJSONObject("gpsData");
//            DeviceGps deviceGps = ComLbsUtils.bigDataGpsFormat(gpsData);
//            photo.setTime(deviceGps.getGdt()).setLocation(deviceGps.getLocation());
//            return photo;
//        }).collect(Collectors.toList());
//
//        //查询所有设备
//        List<EquipmentInfo> equipmentList = equipmentManagementService.selectList(new EquipmentInfo()
//                .setActivateStatus(ActivateStatusEnum.ACTIVATED.getCode()) //已激活设备
//                .setNumberPlateNotEmpty(true));//设备名称不为空
//        //计算摄像头数量
//        int cameraCount = equipmentList.stream()
//                .filter(i -> StringUtils.isNotEmpty(i.getChannels()))
//                .mapToInt(i -> i.getChannels().split(",").length).sum();
        JSONObject resJson = new JSONObjectPro()
                .put("cameraCount", "")
                .put("pageInfo", new Page<>(total, resultList));
        return resJson;
    }

    /**
     * 报警统计
     * @param param
     * @return
     */
    @Override
    public Page<JSONObject> alarmStatistics(AlarmStatisticsParam param){
        //组装大数据接口参数
        JSONObjectPro bigDataParams = new JSONObjectPro()
                .put("page", 1)
                .put("size", 50)
                .put("startTime", DateUtils.parseToTimestamp(param.getStartTime()))
                .put("endTime", DateUtils.parseToTimestamp(param.getEndTime()));


        //远程调用接口
        BigDataResponse<JSONObject> response = HttpRequest.getBigDataNoEncode(bigDataConfig.getApiUrl() + "/dwd/device/alarm/page", bigDataParams, JSONObject.class);
        if (!response.isSuccess()) throw new BigDataException();
//        List<JSONObject> resultList = response.getData().getDataItems();
//        if (ObjectUtils.isEmpty(resultList)) return new Page<>();
//        long total = response.getTotalCount();
        // 提取分页数据
        BigDataResponse.PageData<JSONObject> pageData = response.getData();
        int total = pageData.getTotalCount();
        List<JSONObject> dataItems = pageData.getDataItems();

        // 处理空数据
        if (ObjectUtils.isEmpty(dataItems)) {
            return new Page<>();
        }

        Map<Integer, String> alarmTypeMap = alarmTypeService.selectList(new AlarmType()).stream()
                .collect(Collectors.toMap(AlarmType::getType, AlarmType::getName));
        // 剔除获取不到类型的报警
        dataItems = dataItems.stream().filter(d -> StringUtils.isNotEmpty(alarmTypeMap.get(d.getIntValue("alarmType")))).collect(Collectors.toList());
        List<JSONObject> resultList = new ArrayList<>();
        for (JSONObject item : dataItems) {
            JSONObject one = new JSONObjectPro()
                    .put("numberPlate", item.getString("numberPlate"))
                    .put("time", DateUtils.parseDateTime(new Date(item.getLongValue("gte"))))
                    .put("alarmTypeName", alarmTypeMap.get(item.getIntValue("alarmType")));
            resultList.add(one);
        }
        return new Page<>(total, resultList);
    }
}
